import path from 'path'
import { prisma } from '@/lib/database'
import { FileService } from '@/services/fileService'
import { VulnerabilityService } from '@/services/vulnerabilityService'
import { ValidationError, AppError } from '@/middleware/errorHandler'
// import crypto from 'crypto'
// import fs from 'fs/promises'

// 安全扫描结果类型
export interface SecurityScanResult {
  passed: boolean
  score: number
  issues: SecurityIssue[]
  recommendations: string[]
}

export interface SecurityIssue {
  severity: 'low' | 'medium' | 'high' | 'critical'
  type: string
  description: string
  file?: string
  line?: number
}

export class SecurityService {
  private fileService: FileService
  private vulnerabilityService: VulnerabilityService

  constructor() {
    this.fileService = new FileService()
    this.vulnerabilityService = new VulnerabilityService()
  }

  // 执行插件安全扫描
  async scanPlugin(pluginVersionId: string): Promise<SecurityScanResult> {
    const pluginVersion = await prisma.pluginVersion.findUnique({
      where: { id: pluginVersionId },
      include: {
        plugin: {
          select: {
            name: true,
            displayName: true
          }
        }
      }
    })

    if (!pluginVersion) {
      throw new ValidationError('Plugin version not found')
    }

    console.log(`🔍 Starting security scan for ${pluginVersion.plugin.name} v${pluginVersion.version}`)

    const issues: SecurityIssue[] = []
    const recommendations: string[] = []

    try {
      // 构建完整的文件路径
      const fullFilePath = path.resolve(pluginVersion.filePath)

      // 1. 文件完整性检查
      await this.checkFileIntegrity(fullFilePath, pluginVersion.fileHash)

      // 2. Manifest安全检查
      const manifestIssues = this.checkManifestSecurity(pluginVersion.manifest as any)
      issues.push(...manifestIssues)

      // 3. 权限检查
      const permissionIssues = this.checkPermissions(pluginVersion.permissions)
      issues.push(...permissionIssues)

      // 4. 基础恶意代码检查
      const codeIssues = await this.basicMalwareCheck(fullFilePath)
      issues.push(...codeIssues)

      // 5. 依赖安全检查
      const dependencyIssues = this.checkDependencies(pluginVersion.dependencies as any)
      issues.push(...dependencyIssues)

      // 6. 许可证兼容性检查
      const licenseIssues = this.checkLicenseCompatibility(pluginVersion.manifest as any)
      issues.push(...licenseIssues)

      // 计算安全分数
      const score = this.calculateSecurityScore(issues)

      // 生成建议
      if (issues.length > 0) {
        recommendations.push('Review and address the identified security issues')
      }
      if (score < 70) {
        recommendations.push('Consider improving security practices')
      }

      const result: SecurityScanResult = {
        passed: score >= 70 && !issues.some(i => i.severity === 'critical'),
        score,
        issues,
        recommendations
      }

      // 更新扫描结果
      await prisma.pluginVersion.update({
        where: { id: pluginVersionId },
        data: {
          securityScanStatus: result.passed ? 'passed' : 'failed',
          securityScanResult: result as any
        }
      })

      console.log(`✅ Security scan completed for ${pluginVersion.plugin.name} v${pluginVersion.version}: ${result.passed ? 'PASSED' : 'FAILED'} (Score: ${score})`)

      return result

    } catch (error) {
      console.error(`❌ Security scan failed for ${pluginVersion.plugin.name} v${pluginVersion.version}:`, error)
      
      // 更新扫描状态为失败
      await prisma.pluginVersion.update({
        where: { id: pluginVersionId },
        data: {
          securityScanStatus: 'failed',
          securityScanResult: {
            passed: false,
            score: 0,
            issues: [{
              severity: 'critical',
              type: 'scan_error',
              description: 'Security scan failed to complete'
            }],
            recommendations: ['Contact support for manual review']
          } as any
        }
      })

      throw new AppError('Security scan failed', 500)
    }
  }

  // 检查文件完整性
  private async checkFileIntegrity(filePath: string, expectedHash: string): Promise<void> {
    const actualHash = await this.fileService.generateFileHash(filePath)
    if (actualHash !== expectedHash) {
      throw new ValidationError('File integrity check failed - hash mismatch')
    }
  }

  // 检查Manifest安全性
  private checkManifestSecurity(manifest: any): SecurityIssue[] {
    const issues: SecurityIssue[] = []

    // 检查危险权限
    if (manifest.permissions) {
      const dangerousPermissions = ['execute:system', 'access:filesystem', 'network:unrestricted']
      for (const permission of manifest.permissions) {
        if (dangerousPermissions.includes(permission)) {
          issues.push({
            severity: 'high',
            type: 'dangerous_permission',
            description: `Plugin requests dangerous permission: ${permission}`
          })
        }
      }
    }

    // 检查可疑的配置
    if (manifest.configSchema) {
      const schema = manifest.configSchema
      if (schema.properties) {
        for (const [key, prop] of Object.entries(schema.properties as any)) {
          if (key.toLowerCase().includes('password') || key.toLowerCase().includes('secret')) {
            if (!(prop as any).encrypted) {
              issues.push({
                severity: 'medium',
                type: 'unencrypted_sensitive_config',
                description: `Sensitive configuration field '${key}' should be encrypted`
              })
            }
          }
        }
      }
    }

    return issues
  }

  // 检查权限
  private checkPermissions(permissions: string[]): SecurityIssue[] {
    const issues: SecurityIssue[] = []

    if (!permissions || permissions.length === 0) {
      return issues
    }

    // 检查权限数量
    if (permissions.length > 10) {
      issues.push({
        severity: 'medium',
        type: 'excessive_permissions',
        description: `Plugin requests ${permissions.length} permissions, which may be excessive`
      })
    }

    // 检查特定的高风险权限
    const highRiskPermissions = ['admin:all', 'system:execute', 'network:external']
    for (const permission of permissions) {
      if (highRiskPermissions.includes(permission)) {
        issues.push({
          severity: 'high',
          type: 'high_risk_permission',
          description: `Plugin requests high-risk permission: ${permission}`
        })
      }
    }

    return issues
  }

  // 基础恶意代码检查
  private async basicMalwareCheck(filePath: string): Promise<SecurityIssue[]> {
    const issues: SecurityIssue[] = []

    try {
      // 解析ZIP文件并检查内容
      const packageInfo = await this.fileService.parsePluginPackage(filePath)

      // 检查可疑文件
      const suspiciousFiles = packageInfo.files.filter(file =>
        file.endsWith('.exe') ||
        file.endsWith('.bat') ||
        file.endsWith('.sh') ||
        file.includes('..') || // 路径遍历
        file.includes('node_modules') || // 不应包含node_modules
        file.startsWith('.') // 隐藏文件
      )

      for (const file of suspiciousFiles) {
        let severity: 'low' | 'medium' | 'high' | 'critical' = 'high'
        if (file.endsWith('.exe')) severity = 'critical'
        if (file.includes('..')) severity = 'critical'

        issues.push({
          severity,
          type: 'suspicious_file',
          description: `Suspicious file detected: ${file}`,
          file
        })
      }

      // 检查文件数量（简单的启发式检查）
      if (packageInfo.files.length > 100) {
        issues.push({
          severity: 'low',
          type: 'large_package',
          description: `Package contains ${packageInfo.files.length} files, which may be excessive`
        })
      }

      // 检查代码内容中的可疑模式
      const codeIssues = await this.scanCodeContent(packageInfo)
      issues.push(...codeIssues)

    } catch (error) {
      issues.push({
        severity: 'medium',
        type: 'package_analysis_failed',
        description: 'Failed to analyze package contents'
      })
    }

    return issues
  }

  // 扫描代码内容中的可疑模式
  private async scanCodeContent(packageInfo: any): Promise<SecurityIssue[]> {
    const issues: SecurityIssue[] = []

    // 危险的JavaScript模式
    const dangerousPatterns = [
      { pattern: /eval\s*\(/g, severity: 'high' as const, type: 'dangerous_eval', description: 'Use of eval() function detected' },
      { pattern: /Function\s*\(/g, severity: 'medium' as const, type: 'function_constructor', description: 'Use of Function constructor detected' },
      { pattern: /document\.write/g, severity: 'medium' as const, type: 'document_write', description: 'Use of document.write detected' },
      { pattern: /innerHTML\s*=/g, severity: 'low' as const, type: 'inner_html', description: 'Direct innerHTML assignment detected' },
      { pattern: /require\s*\(\s*['"]child_process['"]/g, severity: 'critical' as const, type: 'child_process', description: 'Use of child_process module detected' },
      { pattern: /require\s*\(\s*['"]fs['"]/g, severity: 'high' as const, type: 'file_system', description: 'Direct file system access detected' },
      { pattern: /XMLHttpRequest|fetch\(/g, severity: 'medium' as const, type: 'network_request', description: 'Network request capability detected' },
      { pattern: /localStorage|sessionStorage/g, severity: 'low' as const, type: 'local_storage', description: 'Local storage access detected' }
    ]

    // 检查JavaScript和TypeScript文件
    const codeFiles = packageInfo.files.filter((file: string) =>
      file.endsWith('.js') || file.endsWith('.ts') || file.endsWith('.jsx') || file.endsWith('.tsx')
    )

    for (const file of codeFiles.slice(0, 20)) { // 限制检查文件数量
      try {
        const content = packageInfo.fileContents?.[file] || ''
        if (typeof content === 'string') {
          for (const { pattern, severity, type, description } of dangerousPatterns) {
            const matches = content.match(pattern)
            if (matches) {
              issues.push({
                severity,
                type,
                description: `${description} in ${file}`,
                file
              })
            }
          }

          // 检查可疑的字符串
          const suspiciousStrings = [
            'password', 'secret', 'token', 'api_key', 'private_key'
          ]

          for (const str of suspiciousStrings) {
            const regex = new RegExp(`['"\`].*${str}.*['"\`]`, 'gi')
            if (regex.test(content)) {
              issues.push({
                severity: 'medium',
                type: 'hardcoded_secrets',
                description: `Potential hardcoded secret detected in ${file}`,
                file
              })
            }
          }
        }
      } catch (error) {
        // 忽略单个文件的解析错误
      }
    }

    return issues
  }

  // 检查依赖安全性（增强版）
  private checkDependencies(dependencies: Record<string, string>): SecurityIssue[] {
    const issues: SecurityIssue[] = []

    if (!dependencies || Object.keys(dependencies).length === 0) {
      return issues
    }

    // 检查依赖数量
    const depCount = Object.keys(dependencies).length
    if (depCount > 50) {
      issues.push({
        severity: 'medium',
        type: 'excessive_dependencies',
        description: `Plugin has ${depCount} dependencies, which significantly increases attack surface`
      })
    } else if (depCount > 20) {
      issues.push({
        severity: 'low',
        type: 'many_dependencies',
        description: `Plugin has ${depCount} dependencies, consider reducing for better security`
      })
    }

    // 检查每个依赖
    for (const [packageName, version] of Object.entries(dependencies)) {
      // 1. 检查是否为恶意包
      if (this.vulnerabilityService.isMaliciousPackage(packageName)) {
        issues.push({
          severity: 'critical',
          type: 'malicious_package',
          description: `Dependency '${packageName}' is a known malicious package`
        })
        continue
      }

      // 2. 检查已知漏洞
      const vulnerabilities = this.vulnerabilityService.checkVulnerabilities(packageName, version)
      for (const vuln of vulnerabilities) {
        issues.push({
          severity: vuln.severity,
          type: 'vulnerable_dependency',
          description: `Dependency '${packageName}@${version}' has vulnerability: ${vuln.title}`,
          file: `package.json (${packageName})`
        })
      }

      // 3. 检查危险的包名模式
      if (this.isDangerousPackageName(packageName)) {
        issues.push({
          severity: 'high',
          type: 'suspicious_package_name',
          description: `Dependency '${packageName}' has suspicious name pattern`
        })
      }

      // 4. 检查版本格式
      if (this.isInsecureVersionRange(version)) {
        issues.push({
          severity: 'medium',
          type: 'insecure_version_range',
          description: `Dependency '${packageName}' uses insecure version range '${version}'`
        })
      }
    }

    return issues
  }

  // 检查是否为危险的包名
  private isDangerousPackageName(packageName: string): boolean {
    const dangerousPatterns = [
      /^[a-z]$/, // 单字符包名
      /\d{10,}/, // 包含长数字序列
      /^(test|demo|example|temp|tmp)$/i, // 测试/临时包名
      /[^a-z0-9\-_.]/i, // 包含特殊字符
      /(admin|root|system|config|secret|password|token|key|auth)/i, // 敏感词汇
      /^(node|npm|yarn|webpack|babel|eslint|prettier)$/i, // 冒充知名工具
    ]

    return dangerousPatterns.some(pattern => pattern.test(packageName))
  }

  // 检查是否为不安全的版本范围
  private isInsecureVersionRange(version: string): boolean {
    // 检查是否使用了不安全的版本范围
    const insecurePatterns = [
      /^\*$/, // 通配符
      /^x$/, // x 通配符
      /^>/, // 大于某版本（没有上限）
      /^>=.*\|\|/, // 复杂的或条件
      /^~0\./, // 0.x 版本的波浪号范围
      /^latest$/, // latest 标签
      /^next$/, // next 标签
      /^beta$/, // beta 标签
      /^alpha$/, // alpha 标签
    ]

    return insecurePatterns.some(pattern => pattern.test(version))
  }

  // 增强的许可证检查
  private checkLicenseCompatibility(manifest: any): SecurityIssue[] {
    const issues: SecurityIssue[] = []

    if (!manifest.license) {
      issues.push({
        severity: 'medium',
        type: 'missing_license',
        description: 'Plugin does not specify a license'
      })
      return issues
    }

    const licenseInfo = this.vulnerabilityService.checkLicenseCompatibility(manifest.license)

    if (!licenseInfo.compatible) {
      issues.push({
        severity: licenseInfo.risk === 'high' ? 'high' : 'medium',
        type: 'incompatible_license',
        description: `Plugin uses incompatible license: ${licenseInfo.name} - ${licenseInfo.description}`
      })
    } else if (licenseInfo.risk === 'medium') {
      issues.push({
        severity: 'low',
        type: 'license_warning',
        description: `Plugin license requires attention: ${licenseInfo.name} - ${licenseInfo.description}`
      })
    }

    return issues
  }

  // 计算安全分数
  private calculateSecurityScore(issues: SecurityIssue[]): number {
    let score = 100

    for (const issue of issues) {
      switch (issue.severity) {
        case 'critical':
          score -= 30
          break
        case 'high':
          score -= 20
          break
        case 'medium':
          score -= 10
          break
        case 'low':
          score -= 5
          break
      }
    }

    return Math.max(0, score)
  }

  // 批量扫描待处理的插件
  async scanPendingPlugins(): Promise<void> {
    const pendingVersions = await prisma.pluginVersion.findMany({
      where: {
        securityScanStatus: 'pending'
      },
      take: 10 // 一次处理10个
    })

    console.log(`🔍 Found ${pendingVersions.length} pending security scans`)

    for (const version of pendingVersions) {
      try {
        await this.scanPlugin(version.id)
      } catch (error) {
        console.error(`Failed to scan plugin version ${version.id}:`, error)
      }
    }
  }
}
